home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / doc / waisprot.txt < prev    next >
Text File  |  1995-05-09  |  31KB  |  1,005 lines

  1. -----------------------------------------------------------------------------
  2.  
  3.                      
  4.             WAIS Protocol Users Manual
  5.  
  6.                      
  7.                    Release 1.0.1
  8.                      
  9.  
  10. Harry Morris 
  11. (morris@think.com)
  12. Thinking Machines Corporation
  13. 3.30.90
  14.  
  15.  
  16.  
  17.      1.0    INTRODUCTION:
  18.      2.0    THE PROTOCOL ARCHITECTURE:
  19.      3.0    THE Z39.50 APDU LIBRARY:
  20.      4.0    THE Z39.50 UTILITY FUNCTIONS:
  21.      5.0     Z39.50 TYPE 1 QUERY
  22.      6.0    INTEGRATION OF WAIS AND Z39.50 LIBRARIES:
  23.      7.0    THE WAIS LIBRARY:
  24.      8.0    WAIS TYPE 1 QUERY:
  25.      9.0    IMPLEMENTATION NOTES:
  26.     10.0    WALK THROUGH OF INIT APDU:
  27.     11.0    WALK THROUGH OF WAIS INIT RESPONSE PROTOCOL EXTENSION:
  28.     12.0    WALK THROUGH OF SAMPLE APPLICATION:
  29.     13.0    ISSUES:
  30.     14.0    SPEC NOTES:
  31.     15.0    DISCLAIMER:
  32.  
  33.  
  34.  
  35. 1.0        INTRODUCTION:
  36.  
  37. The WAIS protocol is an extension to ANSI's Z39.50 protocol.  The
  38. extensions are documented in "WAIS Intgerface Protocol Prototype
  39. Functional Specification Version 1.5" by Franklin Davis. 
  40.  
  41. This document describes an initial implementation of the protocol.
  42. The implementation is in ANSI C.  It is provided in two libraries - 
  43. the base Z39.50 library and the WAIS protocol libarary.  The libraries
  44. define structures for each APDU and element set.  Functions are
  45. provided to build, and destroy the structures.  Each structure can
  46. also be written into a buffer and read from a buffer.  The structure's
  47. representation in the buffer is defined in the specifications.
  48.  
  49.  
  50. 2.0        THE PROTOCOL ARCHITECTURE:
  51.  
  52. The Z39.50 layer provides support for the basic APDU's, utility functions 
  53. for  manipulating tagged data, and hooks for use by the application layer.  
  54.  
  55. The WAIS protocol defines several structures which may be associated with 
  56. APDU's.  It also provides definitions of the Z39.50 hook functions, which 
  57. allow the structures to be read and written.
  58.  
  59. These layers specify the translation of an object (a C struct) to and from
  60. a memory buffer.  The representation within the buffer is that defined in
  61. the Z.39.50 spec.  
  62.  
  63. It is the responsibility of application to construct, send, recieve, and
  64. destroy the Z39.50 and WAIS objects.  
  65.  
  66.  
  67. 3.0        THE Z39.50 APDU LIBRARY:
  68.  
  69. Six APDU's are currently defined: Init,InitResponse,Search,SearchResponse,
  70. Present,PresentResponse.  Other APDU's will be added as time premits.
  71. The C definitions are direct translations of the structures outlined in
  72. appendix A of the Z39.50 spec.  The following functions are provided to
  73. create, destroy, read, and write the respective APDU's.
  74.  
  75.  
  76.     typedef struct InitAPDU {
  77.         pdu_type        PDUType;
  78.         boolean            willSearch,willPresent,willDelete;
  79.         boolean            supportAccessControl,supportResourceControl;
  80.         long            PreferredMessageSize;
  81.         long            MaximumRecordSize;
  82.         char*            IDAuthentication;
  83.         char*            ImplementationID;
  84.         char*             ImplementationName;
  85.         char*            ImplementationVersion;
  86.         any*            ReferenceID;
  87.         void*            UserInformationField;
  88.         } InitAPDU;
  89.     
  90.     InitAPDU* makeInitAPDU(
  91.         boolean search,boolean present,boolean delete,
  92.         boolean accessControl,boolean resourceControl,
  93.         long prefMsgSize,long maxMsgSize,
  94.         char* auth,char* id,char* name, char* version,
  95.         any* refID,any* userInfo);
  96.  
  97.     void freeInitAPDU(InitAPDU* init);
  98.  
  99.     void writeInitAPDU(InitAPDU* init,char* buffer);
  100.  
  101.     InitAPDU* readInitAPDU(char* buffer);
  102.  
  103.  
  104.     typedef struct InitResponseAPDU {
  105.         pdu_type        PDUType;
  106.         boolean            Result;
  107.         boolean            willSearch,willPresent,willDelete;
  108.         boolean            supportAccessControl,supportResourceControl;
  109.         long            PreferredMessageSize;
  110.         long             MaximumRecordSize;
  111.         char*            IDAuthentication;
  112.         char*            ImplementationID;
  113.         char*             ImplementationName;
  114.         char*            ImplementationVersion;
  115.         any*            ReferenceID;
  116.         void*            UserInformationField;
  117.         } InitResponseAPDU;
  118.  
  119.     InitResponseAPDU* makeInitResponseAPDU(
  120.         boolean result,
  121.         boolean search,boolean present,boolean delete,
  122.         boolean accessControl,boolean resourceControl,
  123.         long prefMsgSize,long maxMsgSize,
  124.         char* auth,char* id,char* name, char* version,
  125.         any* refID,any* userInfo);
  126.         
  127.     void freeInitResponseAPDU(InitResponseAPDU* init);
  128.  
  129.     void writeInitResponseAPDU(InitResponseAPDU* init,char* buffer);
  130.  
  131.     InitResponseAPDU* readInitResponseAPDU(char* buffer);
  132.  
  133.     InitResponseAPDU* replyToInitAPDU(InitAPDU* init,boolean result,
  134.         any* userInfo);
  135.         This is a convienience function to create a default InitResponse
  136.         given a response.
  137.  
  138.  
  139.     typedef struct SearchAPDU {
  140.         pdu_type        PDUType;
  141.         long             SmallSetUpperBound;
  142.         long            LargeSetLowerBound;
  143.         long             MediumSetPresentNumber;
  144.         boolean         ReplaceIndicator;
  145.         char*            ResultSetName;
  146.         char**            DatabaseNames;   
  147.         char*            QueryType;
  148.         char**            ElementSetNames;  
  149.         any*            ReferenceID;
  150.         void*            Query;
  151.         } SearchAPDU;
  152.  
  153.     SearchAPDU* makeSearchAPDU(
  154.         long small,long large, long medium,
  155.         boolean replace,char* name,char** databases,char* type,
  156.         char** elements,any* refID,any* queryInfo);
  157.  
  158.     void freeSearchAPDU(SearchAPDU* query);
  159.  
  160.     void writeSearchAPDU(SearchAPDU* query,char* buffer);
  161.     
  162.     SearchAPDU* readSearchAPDU(char* buffer);
  163.  
  164.  
  165.     typedef struct SearchResponseAPDU {
  166.         pdu_type        PDUType;
  167.         long            SearchStatus;
  168.         long            ResultCount;
  169.         long            NumberOfRecordsReturned;
  170.         long             NextResultSetPosition;
  171.         long            ResultSetStatus;
  172.         long             PresentStatus;
  173.         any*            ReferenceID;
  174.         void*            DatabaseDiagnosticRecords;
  175.         } SearchResponseAPDU;
  176.  
  177.     SearchResponseAPDU* makeSearchResponseAPDU(
  178.         boolean result,long count,
  179.         long recordsReturned,long nextPos,
  180.         long resultStatus,long presentStatus,
  181.         any* refID,any* records);
  182.  
  183.     void freeSearchResponseAPDU(SearchResponseAPDU* queryResponse);
  184.  
  185.     void writeSearchResponseAPDU(SearchResponseAPDU* queryResponse,
  186.                                  char* buffer);
  187.  
  188.     SearchResponseAPDU* readSearchResponseAPDU(char* buffer);
  189.  
  190.  
  191.     typedef struct PresentAPDU {
  192.         pdu_type        PDUType;
  193.         long            NumberOfRecordsRequested;
  194.         long            ResultSetStartPosition;
  195.         char*             ResultSetID;
  196.         char*            ElementSetNames; 
  197.         any*            ReferenceID;
  198.         void*            PresentInfo; /* XXX not in Z39.50 spec !!! */
  199.         } PresentAPDU;
  200.  
  201.     PresentAPDU* makePresentAPDU(long recsReq, long startPos,
  202.         char* resultID,any* refID,void* info);
  203.  
  204.     void freePresentAPDU(PresentAPDU* present);
  205.  
  206.     void writePresentAPDU(PresentAPDU* present,char* buffer);
  207.  
  208.     PresentAPDU* readPresentAPDU(char* buffer);
  209.  
  210.  
  211.     typedef struct PresentResponseAPDU {
  212.         pdu_type        PDUType;
  213.         boolean            PresentStatus;
  214.         long            NumberOfRecordsReturned;
  215.         long            NextResultSetPosition;
  216.         any*            ReferenceID;
  217.         void*            DatabaseDiagnosticRecords;
  218.         } PresentResponseAPDU;
  219.  
  220.     PresentResponseAPDU* makePresentResponseAPDU(boolean status, 
  221.         long recsRet,long nextPos,any* refID,any* records);
  222.  
  223.     void freePresentResponseAPDU(PresentResponseAPDU* present);
  224.  
  225.     void writePresentResponseAPDU(PresentResponseAPDU* present,char* buffer);
  226.  
  227.     PresentResponseAPDU* readPresentResponseAPDU(char* buffer);
  228.  
  229.  
  230.  
  231. 4.0        THE Z39.50 UTILITY FUNCTIONS:
  232.  
  233.     The utility functions implement the core Z39.50 datatypes.  They are 
  234.     used internaly by the Z39.50 APDU library functions, and can be used 
  235.     to implement "user information" fields.  They are divided into four 
  236.     categories:
  237.     
  238.         1. Tagged Data Functions - these functions operate on tagged data.
  239.            They are available for use in "user information" fields.
  240.            
  241.         2. Raw Data Functions - these functions are used to implement the
  242.            tagged data functions, and the fixed area of each APDU.  They
  243.            are should not be used for "user information".
  244.         
  245.         3. Version Functions - these functions provide default definitions 
  246.            for the optional version fields.
  247.            
  248.         4. Utility Functions.
  249.  
  250.     Tagged Data Functions:
  251.     
  252.     typedef struct any {    /* an any is a non-ascii string of characters */
  253.         unsigned long    size; 
  254.         char*            bytes;
  255.         } any;
  256.  
  257.     any* makeAny(unsigned int size,char* data);
  258.     void freeAny(any* a);
  259.     any* duplicateAny(any* a);
  260.     char* writeAny(any* a,data_tag tag,char* buffer);
  261.     char* readAny(any** anAny,char* buffer);
  262.     unsigned long writtenAnySize(any* a);
  263.  
  264.     typedef any    bit_map;     /* a bit_map is a group of packed bits */
  265.  
  266.     bit_map* makeBitMap(int numBits,...);
  267.         The variable arguments are boolean "bits".
  268.     void freeBitMap(bit_map* bm);
  269.     boolean bitAtPos(int pos,bit_map* bm);
  270.     char* writeBitMap(bit_map* bm,data_tag tag,char* buffer);
  271.     char* readBitMap(bit_map** bm,char* buffer);
  272.  
  273.     char* writeNum(long num,data_tag tag,char* buffer);
  274.     char* readNum(long* num,char* buffer);
  275.  
  276.     char* writeString(char* s,data_tag tag,char* buffer);
  277.     char* readString(char** s,char* buffer);
  278.         These are convienience functions that can be used anywhere an
  279.         Any is called for.
  280.  
  281.  
  282.     Raw Data Functions:
  283.     
  284.     char* writeCompressedInteger(unsigned int num,char* buf);
  285.     char* readCompressedInteger(unsigned int *num,char* buf);
  286.     char* writeCompressedIntegerWithPadding(unsigned long num,
  287.                                             unsigned int size,char* buffer);
  288.     unsigned long writtenCompressedIntSize(unsigned long num);
  289.         Compressed Integers are described on p. XXX of the Z39.50 document.
  290.     
  291.  
  292.     typedef unsigned long data_tag;
  293.  
  294.     char* writeTag(data_tag tag,char* buf);
  295.     char* readTag(data_tag* tag,char* buf);
  296.     data_tag peekTag(char* buf);
  297.     unsigned long writtenTagSize(data_tag tag);
  298.         
  299.     char* writeByte(unsigned char byte,char* buf);
  300.     char* readByte(unsigned char* byte,char* buf);
  301.  
  302.     char* writeBoolean(boolean flag,char* buf);
  303.     char* readBoolean(boolean* flag,char* buf);
  304.  
  305.     typedef unsigned long pdu_type;
  306.  
  307.     char* writePDUType(pdu_type pduType,char* buf);
  308.     char* readPDUType(pdu_type* pduType,char* buf);
  309.     pdu_type peekPDUType(char* buf);
  310.  
  311.     char* writeBinaryInteger(long num,unsigned int size,char* buf);
  312.     char* readBinaryInteger(long* num,unsigned int size,char* buf);
  313.     unsigned long writtenCompressedBinIntSize(long num);
  314.  
  315.  
  316.     Version Functions:
  317.     
  318.     char* writeProtocolVersion(char* buf);
  319.         Writes the version of the Z39.50 spec that is implemented.
  320.         This implementation is version 1.
  321.         
  322.     char* defaultImplementationID(void);
  323.     char* defaultImplementationName(void);
  324.     char* defaultImplementationVersion(void);
  325.         These functions write default information as suggested by the
  326.         implementers of the protocol.  The application may override
  327.         these fields.
  328.  
  329.  
  330.     Utility Functions:
  331.     
  332.     doList(void** list,void (*func)());
  333.     
  334.  
  335. 5.0     Z39.50 TYPE 1 QUERY
  336.  
  337. The Z39.50 specification defines a type one query as a series of terms, each
  338. of which is of type Attribute, ResultsSet, or Operator.  The the Attribute
  339. terms bind a variable in the current data base (eg. Author = E.A.Poe).  The
  340. ResultSet terms specify a subset of the database.  They are used to store 
  341. intermediate results.  The Operator terms specify an operation relating
  342. Attribute and ResultSet terms (eg. Author = E.A.Poe AND Publisher =
  343. McGraw-Hill).  The terms are gathered on a stack, and evaluated in RPN 
  344. order.  Results are left on the stack for return to the calling program.
  345. The following code defines a query term and provides functions for writing
  346. and reading terms and lists of terms.
  347.  
  348.     typedef struct query_term {
  349.       /* type */
  350.       int    TermType;
  351.       /* for term */
  352.       char    Use[ATTRIBUTE_SIZE];
  353.       char    Relation[ATTRIBUTE_SIZE];
  354.       char    Position[ATTRIBUTE_SIZE];
  355.       char    Structure[ATTRIBUTE_SIZE];
  356.       char    Truncation[ATTRIBUTE_SIZE];
  357.       char    Completeness[ATTRIBUTE_SIZE];
  358.       any*    Term;
  359.       /* for result set */
  360.       any*    ResultSetID;
  361.       /* for operator */
  362.       char    Operator[OPERATOR_SIZE];
  363.     } query_term;
  364.         
  365.     query_term* makeAttributeTerm(
  366.             char* use,char* relation,char* position,char* structure,
  367.             char* truncation,char* completeness,any* term);
  368.     query_term* makeResultSetTerm(any* resultSet);
  369.     query_term* makeOperatorTerm(char* operator);
  370.     void freeTerm(query_term* qt);
  371.     char* writeQueryTerm(query_term* qt,char* buffer);
  372.     char* readQueryTerm(query_term** qt,char* buffer);
  373.     any* writeQuery(query_term** terms);
  374.     query_term** readQuery(any* info);
  375.     
  376.  
  377.  
  378. 6.0        INTEGRATION OF WAIS AND Z39.50 LIBRARIES:
  379.  
  380. The WAIS protocol is implemented through the "user information" field of 
  381. Z39.50's APDU's.  Each Z39.50 APDU has a pointer to user information, and
  382. a hook function to read and write the information.  
  383.  
  384. The functions are:
  385.  
  386.     extern char* writeInitInfo(InitAPDU* init,char* buffer);
  387.     extern char* readInitInfo(void** info,char* buffer);
  388.     
  389.     extern char* writeInitResponseInfo(InitResponseAPDU* init,char* buffer);
  390.     extern char* readInitResponseInfo(void** info,char* buffer);
  391.     
  392.     extern char* writeSearchInfo(SearchAPDU* query,char* buffer);
  393.     extern char* readSearchInfo(void** info,char* buffer);
  394.     
  395.     extern char* writeSearchResponseInfo(SearchResponseAPDU* query,
  396.                                            char* buffer);
  397.     extern char* readSearchResponseInfo(void** info,char* buffer);
  398.     
  399.     extern char* writePresentInfo(PresentAPDU* present,char* buffer);
  400.     extern char* readPresentInfo(void** info,char* buffer);
  401.     
  402.     extern char* writePresentResponseInfo(PresentResponseAPDU* present,
  403.                                           char* buffer);
  404.     extern char* readPresentResponseInfo(void** info,char* buffer);
  405.  
  406. The write functions are called after writing the standard APDU, and only if
  407. the user information field is not NULL.  The read functions are called 
  408. after reading the standard APDU.  They should return NULL if there is no
  409. user information, otherwise they should use the Z39.50 utility functions
  410. to reconstruct the user information as it was written.  
  411.  
  412.  
  413. 7.0        THE WAIS LIBRARY:
  414.     
  415. The WAIS library is devided into two parts.  The first part defines 
  416. structures and code to manipulate the WAIS components which are directly
  417. mapped to Z39.50 APDUs.  The second part defines component structures 
  418. which are used by the WAIS protocol to pass specific elements between the
  419. origin and target.  Note that all objects of the first type also provide 
  420. implementations of the read and write functions described in section 6.0.
  421.  
  422.  
  423.     Basic WAIS Components:
  424.  
  425.     
  426.     typedef struct WAISInitResponse {
  427.         long                ChunkCode;
  428.         long                ChunkIDLength;
  429.         char*                ChunkMarker;
  430.         char*                HighlightMarker;
  431.         char*                 DeHighlightMarker;
  432.         char*                NewlineCharacters;
  433.         /* XXX  need to add UpdateFrequency and Update Time */
  434.         } WAISInitResponse;
  435.     
  436.     WAISInitResponse* makeWAISInitResponse(
  437.         long chunkCode,long chunkIDLen,char* chunkMarker,
  438.         char* highlightMarker,
  439.         char* deHighlightMarker,char* newLineChars);
  440.     void freeWAISInitResponse(WAISInitResponse* init);
  441.  
  442.  
  443.     typedef struct WAISSearch {
  444.         char*                SeedWords;
  445.         DocObj**            Docs;
  446.         char**                TextList;
  447.         long                DateFactor;
  448.         char*                BeginDateRange;
  449.         char*                EndDateRange;
  450.         long                MaxDocumentsRetrieved;
  451.         } WAISSearch;
  452.     
  453.     WAISSearch* makeWAISSearch(
  454.         char* seedWords,DocObj** docs,char** textList,
  455.         long dateFactor,char* beginDateRange,char* endDateRange,
  456.         long maxDocsRetrieved);
  457.     void freeWAISSearch(WAISSearch* query);
  458.  
  459.         
  460.     typedef struct WAISSearchResponse {
  461.         char*                           SeedWordsUsed;
  462.         WAISDocumentHeader**         DocHeaders;
  463.         WAISDocumentShortHeader**     ShortHeaders;
  464.         WAISDocumentLongHeader**     LongHeaders;
  465.         WAISDocumentText**            Text;
  466.         WAISDocumentHeadlines**        Headlines;
  467.         WAISDocumentCodes**            Codes;
  468.         } WAISSearchResponse;
  469.     
  470.     WAISSearchResponse* makeWAISSearchResponse(
  471.         char* seedWordsUsed,WAISDocumentHeader** docHeaders,
  472.         WAISDocumentShortHeader** shortHeaders,
  473.         WAISDocumentLongHeader** longHeaders,
  474.         WAISDocumentText** text,WAISDocumentHeadlines** headlines,
  475.         WAISDocumentCodes** codes);
  476.     void freeWAISSearchResponse(WAISSearchResponse* response);
  477.  
  478.  
  479.     typedef struct WAISPresent {
  480.         DocObj**    Documents; /* type of request is in element set */
  481.         } WAISPresent;
  482.     
  483.     WAISPresent* makeWAISPresent(DocObj** docs);
  484.     void freeWAISPresent(WAISPresent* present);
  485.  
  486.  
  487.     typedef struct WAISPresentResponse {
  488.         WAISDocumentText**        Text;
  489.         WAISDocumentHeadlines**    Headlines;
  490.         WAISDocumentCodes**        Codes;
  491.         } WAISPresentResponse;
  492.  
  493.     WAISPresentResponse* makeWAISPresentResponse(WAISDocumentText** text,
  494.                              WAISDocumentHeadlines** headlines,
  495.                              WAISDocumentCodes** codes);
  496.     void freeWAISPresentResponse(WAISPresentResponse* response);
  497.  
  498.  
  499.     WAIS Elements:
  500.     
  501.         
  502.     typedef struct DocObj { /* specifies a section of a document */
  503.         any*    DocID;
  504.         long    ChunkCode;
  505.         union {
  506.             long    Pos;
  507.             any*    ID;
  508.         } ChunkStart;
  509.         union {
  510.             long    Pos;
  511.             any*    ID;
  512.         } ChunkEnd;
  513.         } DocObj;
  514.  
  515.     DocObj* makeDocObjUsingWholeDocument(any* docID);
  516.     DocObj* makeDocObjUsingBytes(any* docID,long start,long end);
  517.     DocObj* makeDocObjUsingLines(any* docID,long start,long end);
  518.     DocObj* makeDocObjUsingParagraphs(any* docID,any* start,any* end);
  519.     void freeDocObj(DocObj* doc);
  520.         Note that DocObjs are used read and written internally.
  521.  
  522.  
  523.     typedef struct WAISDocumentHeader {
  524.         any*                DocumentID;
  525.         long                VersionNumber;
  526.         long                Score;     
  527.         long                BestMatch; 
  528.         long                DocumentLength;
  529.         long                 Lines;
  530.         char*                Source;
  531.         char*                Date;
  532.         char*                Headline;
  533.         char*                OriginCity;
  534.         } WAISDocumentHeader;
  535.     
  536.     WAISDocumentHeader* makeWAISDocumentHeader(
  537.         any* docID,long versionNumber,long score,long bestMatch,long docLen,
  538.         long lines,char* source,char* date,char* headline,char* originCity);
  539.     void freeWAISDocumentHeader(WAISDocumentHeader* header);
  540.     char* writeWAISDocumentHeader(WAISDocumentHeader* header,char* buffer);
  541.     char* readWAISDocumentHeader(WAISDocumentHeader** header,char* buffer);
  542.     
  543.     
  544.     typedef struct WAISDocumentShortHeader {
  545.         any*                DocumentID;
  546.         long                VersionNumber;
  547.         long                Score;     
  548.         long                BestMatch; 
  549.         long                DocumentLength;
  550.         long                 Lines;
  551.          } WAISDocumentShortHeader;
  552.      
  553.     WAISDocumentShortHeader* makeWAISDocumentShortHeader(
  554.         any* docID,long versionNumber,long score,long bestMatch,
  555.         long docLen,long lines);
  556.     void freeWAISDocumentShortHeader(WAISDocumentShortHeader* header);
  557.     char* writeWAISDocumentShortHeader(WAISDocumentShortHeader* header,
  558.                                        char* buffer);
  559.     char* readWAISDocumentShortHeader(WAISDocumentShortHeader** header,
  560.                                       char* buffer);
  561.  
  562.  
  563.     typedef struct WAISDocumentLongHeader {
  564.         any*                DocumentID;
  565.         long                VersionNumber;
  566.         long                Score;     
  567.         long                BestMatch; 
  568.         long                DocumentLength;
  569.         long                 Lines;
  570.         char*                Source;
  571.         char*                Date;
  572.         char*                Headline;
  573.         char*                OriginCity;
  574.         char*                StockCodes;
  575.         char*                 CompanyCodes;
  576.         char*                IndustryCodes;
  577.          } WAISDocumentLongHeader;
  578.     WAISDocumentLongHeader* makeWAISDocumentLongHeader(
  579.         any* docID,long versionNumber,long score,long bestMatch,long docLen,
  580.         long lines,char* source,char* date, char* headline,char* originCity,
  581.         char* stockCodes,char* companyCodes,char* industryCodes);
  582.     void freeWAISDocumentLongHeader(WAISDocumentLongHeader* header);
  583.     char* writeWAISDocumentLongHeader(WAISDocumentLongHeader* header,
  584.                                       char* buffer);
  585.     char* readWAISDocumentLongHeader(WAISDocumentLongHeader** header,
  586.                                      char* buffer);
  587.  
  588.     
  589.     typedef struct WAISDocumentText {
  590.         any*                DocumentID;
  591.         long                VersionNumber;
  592.         any*                DocumentText;
  593.         } WAISDocumentText;
  594.         
  595.     WAISDocumentText* makeWAISDocumentText(any* docID,long versionNumber,
  596.                            any* documentText);
  597.     void freeWAISDocumentText(WAISDocumentText* docText);
  598.     char* writeWAISDocumentText(WAISDocumentText* docText,char* buffer);
  599.     char* readWAISDocumentText(WAISDocumentText** docText,char* buffer);
  600.     
  601.     
  602.     typedef struct WAISDocumentHeadlines {
  603.         any*                DocumentID;
  604.         long                VersionNumber;
  605.         char*                Source;
  606.         char*                Date;
  607.         char*                Headline;
  608.         char*                OriginCity;
  609.         } WAISDocumentHeadlines;
  610.         
  611.     WAISDocumentHeadlines* makeWAISDocumentHeadlines(
  612.         any* docID,long versionNumber,char* source,char* date,
  613.         char* headline,char* originCity);
  614.     void freeWAISDocumentHeadlines(WAISDocumentHeadlines* docHeadline);
  615.     char* writeWAISDocumentHeadlines(WAISDocumentHeadlines* docHeadline,
  616.                                      char* buffer);
  617.     char* readWAISDocumentHeadlines(WAISDocumentHeadlines** docHeadline,
  618.                                     char* buffer);
  619.     
  620.     
  621.     typedef struct WAISDocumentCodes {
  622.         any*                DocumentID;
  623.         long                VersionNumber;
  624.         char*                StockCodes;
  625.         char*                CompanyCodes;
  626.         char*                IndustryCodes;
  627.         } WAISDocumentCodes;
  628.     
  629.     WAISDocumentCodes* makeWAISDocumentCodes(
  630.         any* docID,long versionNumber,char* stockCodes,char* companyCodes,
  631.         char* industryCodes);
  632.     void freeWAISDocumentCodes(WAISDocumentCodes* docCodes);
  633.     char* writeWAISDocumentCodes(WAISDocumentCodes* docCodes,char* buffer);
  634.     char* readWAISDocumentCodes(WAISDocumentCodes** docCodes,char* buffer);
  635.     
  636.  
  637. 8.0        WAIS TYPE 1 QUERY
  638.  
  639. The WAIS Protocol used type one queries to retrieve fragments of text from
  640. the target.  The syntax is:
  641.        
  642.      1.  retrieve the header/codes from a document:
  643.  
  644.             System_Control_Number = docID    (attribute)
  645.  
  646.          return type is dependent on element set requested
  647.  
  648.      2.  retrieve a fragment of the text of a document:
  649.  
  650.             System_Control_Number = docID    (attribute)
  651.              Chunk >= start                    (attribute)
  652.             And                                (operator)
  653.             Chunk < end                        (attribute)
  654.             And                                (operator)
  655.  
  656.          return type is always WAISDocumentText
  657.  
  658.    Information from multiple documents may be requested by using 
  659.    groups of the above joined by:
  660.  
  661.             OR                                (operator)
  662.  
  663. The following functions translate between list of DocObjs and an any
  664. containing the DocObjs written in the form given above.
  665.  
  666.     any* makeWAISType1Query(DocObj** docs);    
  667.     DocObj** readWAISType1Query(any* terms);
  668.  
  669.  
  670. 9.0        IMPLEMENTATION NOTES:
  671.  
  672.     Z39.50 Types:
  673.     
  674.         ANY    -     Implemented as a structure containing a size field and
  675.                 an arbitrary length block of bytes.  Value is NULL if
  676.                 the element is not present.
  677.                 
  678.         ASCII - Implemented as a C string (null terminated).  
  679.                 Value is NULL if the element is not present.
  680.         
  681.         BitMap -    Implemented as an any, with packed bits.  Value is NULL 
  682.                     if the element is not present.
  683.         
  684.         Data Tag -    Implemented as an unsigned int. 
  685.         
  686.         PduType -    Implemented as an enum.
  687.         
  688.         Binary Integer -     implemented as a long.  Value is UNUSED if the
  689.                             element is not present.
  690.         
  691.  
  692.     Memory Mangement:
  693.     
  694.           Memory management is fairly simple.  The idea is to minimize the 
  695.           copying of large (application specific) data (eg. text buffers),
  696.           while minimizing the amount of explicit freeing that must be
  697.           done by the user of the protocol.
  698.           
  699.           Calls to makeFoo() always copy small arguments and simply reference 
  700.           large arguments.  All Z39.50 APDU's are small, so they always copy.
  701.           All WAIS objects are large, so they always reference.
  702.           
  703.           Calls to freeFoo() always free all elements of foo.
  704.           
  705.           What this means to you:   
  706.           
  707.           1. When making and APDU, be sure to free the arguments (an easy way
  708.              to do this is to use automatic arguments).
  709.           
  710.           2. When making a WAIS object, don't free the arguments (don't use
  711.              automatic arguments).
  712.           
  713.           3. If you want to hold onto part of an object that is about to be
  714.              freed, make a pointer to the part, and NULL out the pointer
  715.              in the object.
  716.              
  717.           This is much harder to explain than to do.  Study the example code
  718.           and/or call the author if you have questions.
  719.           
  720.           
  721. 10.0        WALK THROUGH OF INIT APDU:
  722.  
  723. The Init APDU is a typical of the Z39.50 APDU's.  The pseudo code for its
  724. functions is presented here.
  725.  
  726.  
  727.     makeInitAPDU(boolean willSearch,boolean willPresent,boolean willDelete,
  728.                  boolean supportAccessControl,
  729.                  boolean supportResourceControl,
  730.                  int preferredMessageSize,int maxMessageSize,
  731.                  string authorization,string identification,
  732.                  string implementationName,string implementationVersion,
  733.                  any referenceID,pointer userInformation)
  734.      
  735.     {    Allocate space for an init APDU.
  736.     
  737.         Assign it values based on the arguments.  This may involve checking
  738.         that all required arguments are there, and making copies of some 
  739.         arguments.
  740.         
  741.          Return the new APDU.
  742.     }
  743.   
  744.     
  745.     freeInitAPDU(InitAPDU init)
  746.     
  747.     {     Deallocate any arguments that were copied in makeInitAPDU().
  748.     
  749.         Deallocate the APDU itself.
  750.     }
  751.     
  752.     
  753.     writeInitAPDU(InitAPDU init,memoryBuffer buffer)
  754.     
  755.     {    Declare a pointer buf pointing into buffer, starting HEADER_LEN
  756.         bytes in.
  757.         
  758.         Write init's PDUType at buf, and set buf to the end of the write.
  759.         
  760.         Write the rest of init's data, doing any conversions necessary.
  761.         
  762.         Record the size of APDU (buf - buffer) in the first HEADER_LEN 
  763.         bytes of buffer.
  764.         
  765.         Call writeInitInfo() to write user information into the buffer.        
  766.     }
  767.     
  768.     
  769.     readInitAPDU(memoryBuffer buffer)
  770.     
  771.     {    Declare a pointer buf pointing into the begining of buffer.
  772.     
  773.         Declare local variables for the elements of the APDU.
  774.         
  775.         Read the APDU's size (stored in the first HEADER_LEN bytes).
  776.         
  777.         Read the APDU elements that are reqired to be there.
  778.         
  779.         Decode the ones which are packed (bitmaps)
  780.         
  781.         While buf is less that (buffer + size + HEADER_LEN)
  782.         {     Read the next tag.
  783.             
  784.             Based on the value of the tag, read in an optional element.
  785.             
  786.             Increment buf by the size of the element.
  787.         }
  788.         
  789.         Call readInitInfo() to read user information from the buffer.
  790.         
  791.         Call makeInitAPDU() to create an init APDU.
  792.         
  793.         Deallocate any local variables.
  794.         
  795.         Return the new init APDU.
  796.     }
  797.     
  798.  
  799. 11.0        WALK THROUGH OF WAIS INIT RESPONSE PROTOCOL EXTENSION:
  800.  
  801. The WAIS Init Response is a typical of the Z39.50 protocol extension.  
  802. The pseudo code for its functions is presented here.  It is essentially
  803. identical to that of any of the Z39.50 APDU's.  Note that the reading and
  804. writing routines are Z39.50 hooks.
  805.  
  806.  
  807.     makeWAISInitResponse(int chunkCode,int chunkIDLen,string chunkMarker,
  808.                          string highlightMarker,string deHighlightMarker,
  809.                          string newLineChars)
  810.             
  811.     {    Allocate space for an init response.
  812.     
  813.         Assign it values based on the arguments.  This may involve checking
  814.         that all required arguments are there, and making copies of some 
  815.         arguments.
  816.         
  817.          Return the new response object.
  818.     }
  819.     
  820.     
  821.     freeWAISInitResponse(WAISInitResponse response)
  822.     
  823.     {    Deallocate any arguments that were copied in makeWAISInitResponse().
  824.     
  825.         Deallocate the response itself.
  826.     }
  827.     
  828.     
  829.     writeInitResponseInfo(InitResponseAPDU responseAPDU,memoryBuffer buffer)
  830.  
  831.     {    Declare a pointer response pointing at the user information field
  832.         of responseAPDU.
  833.         
  834.         Estimate the size of the written representation in bytes.  Determine
  835.         how many bytes are needed to represent that size (round up).  Add 
  836.         the size of a tag field, and the size of the size field (always 1). 
  837.         This is the WAIS_HEADER_LEN.
  838.     
  839.            Declare a pointer buf pointing into buffer, starting WAIS_HEADER_LEN
  840.         bytes in.
  841.         
  842.         Write the response's data at buf, doing any conversions necessary.
  843.         
  844.         Record the size of response's size (buf - buffer) in the first 
  845.         WAIS_HEADER_LEN bytes of buffer.
  846.     }
  847.     
  848.     
  849.     readInitResponseInfo(memoryBuffer buffer)
  850.  
  851.     {    Declare a pointer buf pointing into the begining of buffer.
  852.     
  853.         Declare local variables for the elements of the response.
  854.         
  855.         Read the response's size (the first element).
  856.         
  857.         While buf is less that (buffer + size)
  858.         {     Read the next tag.
  859.             
  860.             Based on the value of the tag, read in an element.
  861.             
  862.             Increment buf by the size of the element.
  863.         }
  864.         
  865.         Call makeWAISInitResponse() to create an response object.
  866.         
  867.         Deallocate any local variables.
  868.         
  869.         Return the new response object.
  870.     }
  871.     
  872.  
  873. 12.0    WALK THROUGH OF SAMPLE APPLICATION:
  874.  
  875. This section outlines how an application may play the role of origin or 
  876. target.  The pseudo code will be the same for every APDU. 
  877.  
  878.  
  879.     requestText(document,startLine,endLine)     (for example)
  880.     
  881.     {     Call makeWAISPresent(document,startLine,endLine) to construct a 
  882.         WAIS present object.
  883.     
  884.         Call makePresentAPDU(<z39.50 args>,WAISpresent) to construct a 
  885.         z39.50 present APDU with WAIS present object as its user 
  886.         information.
  887.         
  888.         Call writePresentAPDU(presentAPDU,buffer) to write the APDU and the
  889.         user information to the buffer.
  890.         
  891.         Send the buffer to the target over whatever transport mechanism is
  892.         available.
  893.         
  894.         Free the objects, or store them for future use.
  895.     }
  896.  
  897.     
  898.     recieveAPDU(buffer)
  899.     
  900.     {    Call peekPDUType(buffer) to determine which APDU is in the buffer.
  901.     
  902.         Switch on the result to the appropriate reading routines:
  903.         
  904.             if pdu = initResponseAPDU
  905.                 apdu := readInitAPDU(buffer)
  906.                 
  907.             else if pdu = searchResponseAPDU
  908.                 apdu := readSearchResponseAPDU(buffer)
  909.                 
  910.             else if pdu = presentResponseAPDU
  911.                 apdu := readPresentResponseAPDU(buffer)
  912.                 
  913.          Process the response.
  914.          
  915.          Free the apdu.
  916.     }
  917.  
  918.  
  919. 13.0    ISSUES:
  920.  
  921. The following are some of the open issues which we are still working on
  922. This is not necessarily a complete set.  If you think of more, or
  923. have suggestions on how to approach these, please don't hesitate to contact
  924. the author.
  925.  
  926. - The following parts are defined in the WAIS Protocol Spec 1.5, but are 
  927.   not yet supported in the libraries: Chunk negotiation
  928.   
  929.   
  930. - Although the Present and PresentResponse APDUs (and their matching WAIS
  931.   elements) are defined, they are not officially part of the WAIS protocol
  932.   library, and as such they have not been fully implemented/tested.
  933.   
  934. - The Z39.50 spec does not define the concrete representation of the Present 
  935.   Response APDU.  The structure defined here is a straigtforward translation
  936.   of the abstract representation.
  937.  
  938. - The spec does not provide for a user information field in the Present 
  939.   APDU.  We have added one, and believe it should be made a standard part of the
  940.   spec.
  941.  
  942. - We do not check to ensure that the refID fields are limited to 64 
  943.   characters as outlined in the spec.
  944.  
  945. - We do nothing to respect MaximumRecordSize
  946.  
  947. - Fix up naming conventions - should all these functions be prefixed with
  948.   "Z3950_" to prevent name collisions?
  949.  
  950. - Add support for other apdu's.
  951.  
  952. - Check consistency with spec.
  953.  
  954. - Test portability to other platforms - Partial port to Saber-C on Sun
  955.   platforms is successful.
  956.  
  957. - We need a way for servers to indicate what chunk sizes they will support.
  958.   This could be done in the init/initResponse APDUs by passing a bitmap
  959.   with the bit at possition N specifying the availablity of chunk size N.
  960.   There are other difficulties with Chunks that the are under consideration
  961.   at Thinking Machines.
  962.   
  963. - The use of malloc will contribute to fragmentation of the heap which
  964.   may be unacceptable on machines w/o virtual memory (macs).  We may
  965.   need a more abstract memory model.
  966.   
  967.  
  968. 14.0    SPEC NOTES:
  969.  
  970. There are several issues alluded to in the spec that are not directly 
  971. addressed.  They are discussed here.
  972.  
  973. - The size of a Binary integer is unspecified.  We have chosen to use C long
  974.   ints (4 bytes).  When writing them in a variable section, we use only as
  975.   many bytes as are required to represent their data.
  976.  
  977.  
  978. 14.0    DISCLAIMER:
  979.  
  980. The libraries described here are initial implementations and are 
  981. subject to change.  We will make every effort to stabilize the
  982. libraries as soon as possible, and to inform all users of changes.
  983.  
  984. One of our first goals will be to confirm that the implementation
  985. actually conforms to the Z39.50 specification.  The WAIS protocol
  986. will undoubtably evolve over time as we gain experience with developing
  987. information servers and clients.
  988.  
  989. These libraries will be placed in the public domain as soon as they
  990. are suitably stable.  Until Thinking Machines releases the libraries,
  991. please do not distribute the libraries without first contacting the
  992. author.
  993.  
  994. As always, if there is a discrepancy between the documentation and the
  995. code - believe the code.
  996.  
  997.  
  998.  
  999.  
  1000. 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  1001.  
  1002.  
  1003.  
  1004.  
  1005.